function Server(socket){
    this.__ids = 0;
    var __self = this;
    this.socket = socket;
    this.socket.on("message", function(data){
        __self.fire(data[type], data[data]);
    });
}

Server.prototype.createID = function(){
    return ++this.__ids;
}

Server.prototype.sendMessage = function(type, data){
    this.socket.emit("message", {
        type : type,
        data : data
    });
}

//@deprecated
Server.prototype.synchronize = function() {
    var entities = this.stage.entities;
	var i = entities.length;
	while(i--){
		if(!entities[i].__netID) entities[i] = this.createID();
		var attributes = {};
		for(attr in entities[i]){
			if(typeof entities[i][attr] != "function"){
				attributes[attr] = entities[i][attr];
			}
		}
		attributes.__class = entities[i].getClassName();
		this.socket.emit("sync_entity", attributes);
	}
}

//@deprecated
Server.prototype.setStage = function(stage){
    this.stage = stage;
    this.stage.on("update", this.synchronize);
    this.__ids = 0;
    var entities = this.stage.entities;
	var i = entities.length;
	while(i--){
		 if(!entities[i].__netID) entities[i] = this.createID();
	}
    this.socket.emit("sync_stage", stage);
}

function Client(socket){
    var __self = this;
    this.socket = socket;
    this.socket.on("sync_stage", function(entities){
        __self.onStage.call(__self, entities);
    });
    this.socket.on("sync_entity", function(attibutes){
        __self.onSynchronize.call(__self, attributes);
    });
}

Client.prototype.onStage = function(stage){
    this.stage = stage;
}

Client.prototype.onSynchronize = function(entity){
    var s = this.stage;
    var entities = s.entities;
    var entityFound = false;
	var i = entities.length;
	while(i--){
		if(entities[i].__netID == entity.__netID){
            for(attr in entity){
                if(attr != "__class"){
                    entities[i][attr] = attributes[attr];
                }
            }
            entityFound = true;
        }
	}
    if(entityFound === false){
        var cls = entity["__class"];
        eval("__tmp = new " + cls + "();");
        var e = __tmp;
        delete __tmp;
        for(attr in entity){
            if(attr != "__class"){
                e[attr] = attributes[attr];
            }
        }
        s.addEntity(e);
    }
}

Client.prototype.sendMessage = function(type, data){
    this.socket.emit("message", {
        type : type,
        data : data
    });
}

function Network(){
    if (typeof Network.__instance === "object") {
        return Network.__instance;
    }
    this.socket = io.connect('http://localhost');
    Network.__instance = this;
}

Network.prototype.findServers = function(callback){
    var s = this.socket;
    var cb = function(servers){
        callback(servers);
        s.removeListener("server_list", cb);
    };
    s.emit("request_server_list");
    s.on("server_list", cb);
}

Network.prototype.createServer = function(name, callback){
    var s = this.socket;
    var cb = function(name){
        callback(new Server(s));
        s.removeListener("server_created", cb);
    }
    s.emit("create_server", name);
    s.on("server_created", cb);
}

Network.prototype.joinServer = function(name, callback){
    var s = this.socket;
    var cb = function(name){
        callback(new Client(s));
        s.removeListener("server_joined", cb);
    }
    s.emit("join_server", name);
    s.on("server_joined", cb);
}